/*
 * @Descripttion: Lutongli代码
 * @version: 1.0.0
 * @Author: LutongLi
 * @Date: 2025-05-29 00:16:21
 * @LastEditTime: 2025-06-02 16:15:40
 */
package conf
import("sync"
		_ "github.com/go-sql-driver/mysql"
		"time"
		"fmt"
		"context"
		"database/sql"
)

//要想获取配置，单独提供一个函数
//全局配置C获取函数
func C() *Config{
	return config
}


//Config应用配置
//通过封装为一个对象，来与外部进行对接
type Config struct{
	App *APP `toml:"app"`
	Log *Log `toml:"log"`
	MySQL *MySQL `toml:"mysql"`
}

//关于app的配置
type APP struct{
	Name string `toml: "name" env:"APP_NAME`
	Host string `toml:"host" env:"APP_HOST"`
	Port string `toml:"port" env:"APP_PORT"`
	// Key string `toml:"key" env: "APP_KEY"`
	// EnableSSL bool `toml:"enable_ssl" env: "APP_ENABLE_SSL"`
	// CertFile string `toml:"cert_file" env: "APP_CERT_FILE`
	// KeyFile string `toml:"key_file" env:"APP_KEY_FILE"`
}

func (a *APP) HttpAddr() string{
	return fmt.Sprintf("%s:%s",a.Host,a.Port)
}


//关于数据库mysql的配置
type MySQL struct{
	Host string `toml:"host" env:"MYSQL_HOST"`
	Port string `toml:"port" env:"MYSQL_PORT"`
	UserName string `toml:"username" env:"MYSQL_USERNAME"`
	Password string `toml:"password" env:"MYSQL_PASSWORD"`
	Database string `toml:"database" env:"MYSQL_DATABASE"`
	//使用mysql的连接池
	//控制当前程序的mysql打开的连接数
	MaxOpenConn int `toml:"max_open_conn" env:"MYSQL_MAX_OPEN_CONN"` //连接池的最大连接数
	MaxIdleConn int `toml:"max_idle_conn" env:"MYSQL_MAX_IDLE_CONN"` //控制mysql的复用连接数量
	MaxLifeTime int `toml:"max_life_time" env:"MYSQL_MAX_LIFE_TIME"` //一个连接的生命周期，这个值必须小于mysql server的配置
	MaxIdleTime int `toml:"max_idle_time" env:"MYSQL_MAX_IDLE_TIME"` //一个连接最大存活时间，过了这个时间，就会被回收
	lock sync.Mutex

}

//log todo
type Log struct{
	Level string	`toml:"level" env:"LOG_LEVEL"`
	PathDir string `toml:"path_dir" env:"LOG_PATH_DIR"`
	Format LogFormat `toml:"format" env:"LOG_FORMAT"`
	To  LogTo	`toml:"to" env:"LOG_TO"`
	
}

//以下为默认配置

//初始化一个config的默认对象
func NewDefaultConfig() *Config{
	return &Config{
		App: NewDefaultAPP(),
		Log: NewDefaultLog(),
		MySQL: NewDefaultMySQL(),
	}
}

func NewDefaultAPP() *APP {
	return &APP{
		Name: "demo",
		Host: "127.0.0.1",
		Port: "8050",
		// Key: "default", //用于加密/解密用的
	}
}

func NewDefaultLog() *Log {
	return &Log{
		//debug info warn error
			Level: "debug",
			PathDir: "logs",
			Format: TextFormat,
			To: "stdout",
	}
}

func NewDefaultMySQL() *MySQL {
	return &MySQL{
		Host: "127.0.0.1",
		Port: "3306",
		// UserName: "lutongli",
		// Password: "tt123123",
		// Database: "lutongli",
		MaxOpenConn: 200,
		MaxIdleConn:100,
		// MaxLifeTime: 60 * 60,
		// MaxIdleTime: 60 * 60,


	}
}

func (a *APP)Addr() string{
	return a.Host + ":" + a.Port
}

func (m *MySQL) getDBConn()(*sql.DB,error){
	var err error
	//id:password@tcp(your-amazonaws-uri.com:3306)/dbname
	dsn := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?charset=utf8&multiStatements=true",m.UserName,m.Password,m.Host,m.Port,m.Database)
	db,err := sql.Open("mysql",dsn)
	if err != nil{
		return nil,fmt.Errorf("connect to mysql<%s> error,%s",dsn,err.Error())
	}
	db.SetMaxOpenConns(m.MaxOpenConn)
	db.SetMaxIdleConns(m.MaxIdleConn)
	db.SetConnMaxLifetime(time.Second *time.Duration(m.MaxLifeTime))
	db.SetConnMaxIdleTime(time.Second * time.Duration(m.MaxIdleTime))
	ctx,cancel := context.WithTimeout(context.Background(),5*time.Second)
	defer cancel()
	if err := db.PingContext(ctx);err != nil{
		return nil,fmt.Errorf("ping mysql <%s> error,%s",dsn,err.Error())
	}
	return db,nil
}

//1.第一种方式，使用loadglobal在加载时，初始化全局db实例
//2.第二种方式，惰性加载，判断是否有，没有的话，再初始化

//1.第一种方式，使用loadglobal在加载时，初始化全局db实例
func loadGlobalMysql()(err error){
	db,err = config.MySQL.getDBConn()
	if err != nil {
		return
	}
	return
}

//2.第二种方式，惰性加载，判断是否有，没有的话，再初始化
func(m *MySQL)GetDB() *sql.DB {
	m.lock.Lock()
	defer m.lock.Unlock()
	//如果实例不存在，就会初始化一个新的实例
	if db == nil {
		conn,err := m.getDBConn()
		if err != nil{
			panic(err)
		}
		db = conn
	}
	
	return db
}
